﻿/*********************************************
 * CLR 版本：       4.0.30319.42000
 * 类 名 称：       Logger
 * 机器名称：       MS-20170310FLQY
 * 命名空间：       Utils
 * 文 件 名：       Logger
 * 创建时间：       2017/5/12 10:16:17
 * 作    者：       Choj
 * 说    明：     
 * 修改时间：
 * 修 改 人：
 * 
*********************************************/
using System;
using System.IO;
using System.Text;
using System.Threading;

namespace AiYard.Common

{
    /// <summary>
    /// 异步日志实现类
    /// </summary>
    public class AiLogger
    {
        #region 属性
        /// <summary>
        /// 实例化
        /// </summary>
        public static AiLogger Instance = new AiLogger();
        /// <summary>
        /// 日志保存的路径
        /// </summary>
        string LogPath = System.IO.Directory.GetCurrentDirectory();
        /// <summary>
        /// 文件夹路径
        /// </summary>
        string LogDir = "Logger";
        /// <summary>
        /// 文件夹路径
        /// </summary>
        string LogDateFormat = "yyyyMMdd";
        #endregion

        #region 构造函数
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public AiLogger()
        { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="LogDir">日志的文件夹</param>
        public AiLogger(string LogDir)
        {
            this.LogDir = LogDir;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="path"></param>
        /// <param name="LogDir"></param>
        public AiLogger(string path, string LogDir)
        {
            this.LogPath = path;
            this.LogDir = LogDir;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="LogDir">日志路径</param>
        /// <param name="logDateFormat">文件格式</param>

        public AiLogger(string path, string logDir, string logDateFormat)
        {
            this.LogPath = path;
            this.LogDir = logDir;
            this.LogDateFormat = logDateFormat;
        }
        #endregion

        #region 错误日志记录
        /// <summary>
        /// 添加错误日志
        /// </summary>
        /// <param name="ex">错误的信息</param>
        /// <param name="parms">其他的参数</param>
        public void Error(Exception ex, params object[] parms)
        {
            try
            {
                var strMsg = new StringBuilder();
                strMsg.AppendFormat("\r\n");
                strMsg.AppendFormat("Message:{0}", ex.Message);
                strMsg.AppendFormat("\r\n");
                strMsg.AppendFormat("StackTrace:{0}", ex.StackTrace);
                strMsg.AppendFormat("\r\n");
                strMsg.AppendFormat("source:{0}", ex.Source);
                strMsg.AppendFormat("\r\n");
                strMsg.AppendFormat("InnerException:{0}", ex.InnerException);
                strMsg.AppendFormat("\r\n");
                AddQueue(strMsg.ToString(), "异常", parms);
            }
            catch
            { }
        }

        /// <summary>
        /// 调试日志
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的参数</param>
        public void Debug(string msg, params object[] parms)
        {
            AddQueue(msg, "调试", parms);
        }

        /// <summary>
        /// 调试日志
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的参数</param>
        public void Info(string msg, params object[] parms)
        {
            AddQueue(msg, "信息", parms);
        }


        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的参数</param>
        public void Warn(string msg, params object[] parms)
        {
            AddQueue(msg, "警告", parms);
        }

        /// <summary>
        /// 错误
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的参数</param>
        public void Error(string msg, params object[] parms)
        {
            AddQueue(msg, "错误", parms);
        }


        /// <summary>
        /// 致命错误
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的参数</param>
        public void Fatal(string msg, params object[] parms)
        {
            AddQueue(msg, "致命错误", parms);
        }
        /// <summary>
        /// 写一般日志
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="fileName"></param>
        /// <param name="parms"></param>
        public void WriteLog(string msg, string fileName, params object[] parms)
        {
            AddQueue(msg, fileName, parms);
        }
        #endregion

        #region 添加日志到队列
        /// <summary>
        /// 添加日志到队列
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="level"></param>
        /// <param name="parms"></param>
        private void AddQueue(string msg, string level, params object[] parms)
        {
            try
            {
                QueueHelper<LogEntity>.Instance.Enqueue(new LogEntity()
                {
                    Level = level,
                    Msg = msg,
                    Parms = parms,
                    InTime = DateTime.Now
                });
            }
            catch
            { }
        }
        #endregion

        #region 保存日志信息
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            ThreadPool.QueueUserWorkItem(o =>
            {
                while (true)
                {
                    try
                    {
                        var queue = QueueHelper<LogEntity>.Instance.Dequeue();
                        if (queue != null)
                        {
                            try
                            {
                                #region 基本的设置

                                string path = LogPath;
                                if (string.IsNullOrEmpty(path))
                                {
                                    path = System.AppDomain.CurrentDomain.BaseDirectory;
                                }
                                path = string.Format("{0}\\{1}\\{2}\\", path, LogDir, DateTime.Now.ToString(LogDateFormat));
                                while (path.Contains(@"\\"))
                                {
                                    path = path.Replace(@"\\", @"\");
                                }
                                if (!Directory.Exists(path))
                                {
                                    Directory.CreateDirectory(path);
                                }
                                var fileName = queue.Level + ".log";
                                string filePath = path + fileName;
                                #endregion

                                using (var sw = new StreamWriter(filePath, true))
                                {
                                    var strMsg = new StringBuilder();

                                    strMsg.AppendFormat(queue.InTime.ToString("yyyy-MM-dd HH:mm:ss.fff") + "-->{0}", queue.Msg);
                                   
                                    if (queue.Parms != null)
                                    {
                                        //--- 其他的参数 ---
                                        foreach (var parm in queue.Parms)
                                        { 
                                            strMsg.Append("-->" + parm);
                                        }
                                    } 
                                    sw.WriteLine(strMsg.ToString());
                                }
                            }
                            catch
                            { }
                        }
                    }
                    catch
                    { }
                    Thread.Sleep(1);
                }
            });
        }
        #endregion
    }

    /// <summary>
    /// 保存日志
    /// </summary>
    public class LogEntity
    {
        private string msg;
        /// <summary>
        /// 日志基本信息
        /// </summary>
        public string Msg
        {
            get { return msg; }
            set { msg = value; }
        }

        private string level;
        /// <summary>
        /// 日志等级
        /// </summary>
        public string Level
        {
            get { return level; }
            set { level = value; }
        }

        private object[] parms;
        /// <summary>
        /// 其他的参数
        /// </summary>
        public object[] Parms
        {
            get { return parms; }
            set { parms = value; }
        }

        private DateTime inTime;
        /// <summary>
        /// 入队时间
        /// </summary>
        public DateTime InTime
        {
            get { return inTime; }
            set { inTime = value; }
        }
    }
}
